package com.mathdroid.model.abilities.optimizer;

import java.util.LinkedList;

import com.mathdroid.model.abilities.Ability;

/**
 * This is a list of ability optimizer results. The list is ordered by result-
 * rating. The highest ratings have the lowest index in this list. This list
 * contains up to MAX_SIZE results.
 */
public final class AbilityOptimizerResultList 
extends LinkedList<AbilityOptimizerResult> {

	/**
	 * Generated UID.
	 */
	private static final long serialVersionUID = 3907112928998144899L;
	
	/**
	 * The maximum amount of results this list should hold.
	 */
	private static final int MAX_SIZE = 100;

	/**
	 * Use this method to offer an result to this limited result list.
	 * @param r Result to offer.
	 * @return If the result was added.
	 */
	public boolean offer(final AbilityOptimizerResult r) {
		boolean inserted = false;
		int k = -1;

		
		/*
		 * Go through this list from the highest to the lowest index.
		 */
		for (int i = this.size() - 1; i >= 0; i--) {
			
			/*
			 * If the element at position i has a worse rating that object r,
			 * remember the index to insert object r at this position, but try
			 * to find an even better position in the list in the next 
			 * iteration.
			 */
			if (this.get(i).getRating() < r.getRating()) {
				k = i;
			} else {
				break;
			}
		}
		
		/*
		 * If "k" still is "-1", the object r is worse that the worst element
		 * in the list. But if it is better, then insert it at index "k".
		 */
		if (k != -1) {
			this.add(k, r);
			inserted = true;
			/* 
			 * Now the list can be bigger than MAX_SIZE, so maybe remove the 
			 * last element. 
			 */
			if (this.size() > MAX_SIZE) {
				this.removeLast();
			}
			
		/*
		 * "k" can be "-1" if the list was empty, so insert it anyways. Also
		 * the object can be inserted anyways if the MAX_SIZE isn't reached.
		 */
		} else if (this.size() < MAX_SIZE || this.size() == 0) {
			/* Use the super method! */
			this.add(r);
			inserted = true;
		}
		
		return inserted;
	}
	
	@Override
	public String toString() {
		String s = new String();
		
		for (AbilityOptimizerResult r : this) {
			s = s.concat(r.getRating() + "\t");
			for (Ability a : r.getPrio()) {
				s = s.concat(a.getName());
			}
			s = s.concat("\n");
		}
		
		return s;
	}
}
